#include "ohos_init.h"
#include "cmsis_os2.h"
#include "los_task.h"
#include "lz_hardware.h"
#include "config_network.h"
#include "lwip/tcp.h"
#include "lwip/ip_addr.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/stats.h"
#include "lwip/inet_chksum.h"
#include "cJSON.h"

#include "tcp.h"
#include "device_mgr.h"

char g_message_send[BUFF_LEN];

int g_client_fd = -1; // 客户端socket描述符
int get_wifi_info(WifiLinkedInfo *info)
{
    int ret = -1;
    int gw, netmask;
    memset(info, 0, sizeof(WifiLinkedInfo));
    unsigned int retry = 15;
    while (retry)
    {
        if (GetLinkedInfo(info) == WIFI_SUCCESS)
        {
            if (info->connState == WIFI_CONNECTED)
            {
                if (info->ipAddress != 0)
                {
                    LZ_HARDWARE_LOGD(LOG_TAG, "rknetwork IP (%s)", inet_ntoa(info->ipAddress));
                    if (WIFI_SUCCESS == GetLocalWifiGw(&gw))
                    {
                        LZ_HARDWARE_LOGD(LOG_TAG, "network GW (%s)", inet_ntoa(gw));
                    }
                    if (WIFI_SUCCESS == GetLocalWifiNetmask(&netmask))
                    {
                        LZ_HARDWARE_LOGD(LOG_TAG, "network NETMASK (%s)", inet_ntoa(netmask));
                    }
                    if (WIFI_SUCCESS == SetLocalWifiGw())
                    {
                        LZ_HARDWARE_LOGD(LOG_TAG, "set network GW");
                    }
                    if (WIFI_SUCCESS == GetLocalWifiGw(&gw))
                    {
                        LZ_HARDWARE_LOGD(LOG_TAG, "network GW (%s)", inet_ntoa(gw));
                    }
                    if (WIFI_SUCCESS == GetLocalWifiNetmask(&netmask))
                    {
                        LZ_HARDWARE_LOGD(LOG_TAG, "network NETMASK (%s)", inet_ntoa(netmask));
                    }
                    ret = 0;
                    goto connect_done;
                }
            }
        }
        LOS_Msleep(1000);
        retry--;
    }

connect_done:
    return ret;
}

int analyse_msg(char *msg, int msg_len)
{
    if (msg == NULL || msg_len <= 0)
    {
        return -1;
    }

    cJSON *root = cJSON_ParseWithLength(msg, msg_len);
    if (root == NULL)
    {
        printf("[tcp server] analyse_msg: cJSON_Parse failed!\n");
        return -1;
    }

    printf("analyse_msg begin...\n");
    cJSON *control_object = cJSON_GetObjectItem(root, "root");
    cJSON *service_type = cJSON_GetObjectItem(root, "service_type");
    if (control_object != NULL && service_type != NULL)
    {
        char *control_object_str = cJSON_GetStringValue(control_object);
        char *service_type_str = cJSON_GetStringValue(service_type);
        if (control_object_str != NULL && service_type_str != NULL)
        {
            if (strcmp(control_object_str, "SMART_HOUSE") != 0 || strcmp(service_type_str, "control_command") != 0)
            {
                printf("[tcp server] analyse_msg: message type error!\n");
                cJSON_Delete(root);
                cJSON_Delete(control_object);
                cJSON_Delete(service_type);
                return -1;
            }
        }
        else
        {
            printf("[tcp server] analyse_msg: control_object_str or service_type_str is NULL!\n");
            cJSON_Delete(root);
            return -1;
        }
    }
    else
    {
        printf("[tcp server] analyse_msg: control_object or service_type is NULL!\n");
        cJSON_Delete(root);
        return -1;
    }

    cJSON *messages = cJSON_GetObjectItem(root, "message");
    cJSON *message = NULL;
    if (messages != NULL)
    {
        message = cJSON_GetArrayItem(messages, 0);
        if (message == NULL)
        {
            printf("[tcp server] analyse_msg: message is NULL!\n");
            cJSON_Delete(root);
            return -1;
        }
    }

    cJSON *item = NULL;
    cJSON_ArrayForEach(item, messages)
    {
        if (item == NULL)
        {
            printf("[tcp server] analyse_msg: item is NULL!\n");
            cJSON_Delete(root);
            return -1;
        }

        cJSON *device = cJSON_GetObjectItem(item, "device");
        cJSON *device_sta = cJSON_GetObjectItem(item, "device_sta");
        if (device == NULL || device_sta == NULL)
        {
            printf("[tcp server] analyse_msg: device or device_sta is NULL!\n");
            cJSON_Delete(root);
            return -1;
        }

        if (strcmp(cJSON_GetStringValue(device), "garage_door") == 0)
        {
            char *garage_door_str = cJSON_GetStringValue(device_sta);
            if (garage_door_str != NULL)
            {
                if (strcmp(garage_door_str, "ON") == 0)
                {
                    g_is_garage_door_open = true;
                }
                else if (strcmp(garage_door_str, "OFF") == 0)
                {
                    g_is_garage_door_open = false;
                }
                else
                {
                    printf("[tcp server] analyse_msg: garage_door state error!\n");
                }
            }
            else
            {
                printf("[tcp server] analyse_msg: garage_door_str is NULL!\n");
            }
        }
        else if (strcmp(cJSON_GetStringValue(device), "entry_door") == 0)
        {
            char *entry_door_str = cJSON_GetStringValue(device_sta);
            if (entry_door_str != NULL)
            {
                if (strcmp(entry_door_str, "ON") == 0)
                {
                    g_is_entry_door_open = true;
                }
                else if (strcmp(entry_door_str, "OFF") == 0)
                {
                    g_is_entry_door_open = false;
                }
                else
                {
                    printf("[tcp server] analyse_msg: entry_door state error!\n");
                }
            }
        }
        else if (strcmp(cJSON_GetStringValue(device), "window") == 0)
        {
            char *window_str = cJSON_GetStringValue(device_sta);
            if (window_str != NULL)
            {
                if (strcmp(window_str, "ON") == 0)
                {
                    g_is_window_open = true;
                }
                else if (strcmp(window_str, "OFF") == 0)
                {
                    g_is_window_open = false;
                }
                else
                {
                    printf("[tcp server] analyse_msg: window state error!\n");
                }
            }
        }
        else if (strcmp(cJSON_GetStringValue(device), "light_sta") == 0)
        {
            char *light_str = cJSON_GetStringValue(device_sta);
            if (light_str != NULL)
            {
                if (strcmp(light_str, "ON") == 0)
                {
                    g_is_light_on = true;
                }
                else if (strcmp(light_str, "OFF") == 0)
                {
                    g_is_light_on = false;
                }
                else
                {
                    printf("[tcp server] analyse_msg: light state error!\n");
                }
            }
        }
    }

    // 解析消息内容
    return 0;
}
void tcp_server_msg_handle(int fd)
{
    char buf[BUFF_LEN]; // 接收缓冲区
    socklen_t client_addr_len;
    int cnt = 0, count;
    int client_fd;
    struct sockaddr_in client_addr = {0};

    printf("waitting for client connect...\n");
    /* 监听socket 此处会阻塞 */
    client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_addr_len);
    g_client_fd = client_fd; // 保存客户端socket描述符
    printf("[tcp server] accept <%s:%d>\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
    while (1)
    {
        memset(buf, 0, BUFF_LEN);
        printf("-------------------------------------------------------\n");
        printf("[tcp server] waitting client msg\n");
        count = recv(client_fd, buf, BUFF_LEN, 0); // read是阻塞函数，没有数据就一直阻塞
        if (count == -1)
        {
            printf("[tcp server] recieve data fail!\n");
            LOS_Msleep(3000);
            break;
        }
        printf("[tcp server] rev client msg:%s\n", buf);
        analyse_msg(buf, count);
    }
    lwip_close(client_fd);
    lwip_close(fd);
}

int wifi_server(void *arg)
{
    int server_fd, ret;

    while (1)
    {
        server_fd = socket(AF_INET, SOCK_STREAM, 0); // AF_INET:IPV4;SOCK_STREAM:TCP
        if (server_fd < 0)
        {
            printf("create server socket fail! socket_fd =%d\n", server_fd);
            // return -1;
            continue;
        }

        /*设置调用close(socket)后,仍可继续重用该socket。调用close(socket)一般不会立即关闭socket，而经历TIME_WAIT的过程。*/
        int flag = 1;
        ret = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
        if (ret != 0)
        {
            printf("[CommInitTcpServer]setsockopt fail, ret[%d]!\n", ret);
        }

        struct sockaddr_in serv_addr = {0};
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // IP地址，需要进行网络序转换，INADDR_ANY：本地地址
        serv_addr.sin_port = htons(LISTEN_PORT);       // 端口号，需要网络序转换
        /* 绑定服务器地址结构 */
        ret = bind(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
        if (ret < 0)
        {
            printf("socket bind fail!\n");
            lwip_close(server_fd);
            // return -1;
            continue;
        }
        /* 监听socket 此处不阻塞 */
        ret = listen(server_fd, 64);
        if (ret != 0)
        {
            printf("socket listen fail!\n");
            lwip_close(server_fd);
            // return -1;
            continue;
        }
        printf("[tcp server] listen:%d<%s:%d>\n", server_fd, inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
        tcp_server_msg_handle(server_fd); // 处理接收到的数据
        LOS_Msleep(1000);
    }
}

int wifi_client(void *arg)
{
    printf("------------wifi_client enter------------\n");
    int client_fd, ret;
    struct sockaddr_in serv_addr;

    while (1)
    {
        if (g_client_fd < 0)
        {
            printf("create client socket fail!\n");
            LOS_TaskDelay(1000);
            continue;
        }

        int snd_msg_len = send(g_client_fd, g_message_send, strlen(g_message_send), 0); // 发送数据给server
        if (snd_msg_len < 0)
        {
            printf("send data failed! snd_msg_len = %d\n", snd_msg_len);
            LOS_TaskDelay(1000);
            continue;
        }

        LOS_Msleep(1000);
    }

    return 0;
}

